#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <string>

#include "LockGuard.hpp"

using namespace std;

int cnt = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* Count(void* args)
{
    pthread_detach(pthread_self());
    uint64_t number = (uint64_t)args; 
    cout << "thread[" << number << "]$ " << number  << " create success!\n";

    while (true)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);   // pthread_cond_wait让线程等待时，会自动释放锁。 
        cout << "thread[" << number << "]$ " << number  << ", cnt: "<< cnt++ << endl;
        pthread_mutex_unlock(&mutex);

    }

}

int main()
{
    for(uint64_t i = 0; i < 5; ++i)
    {
        pthread_t tid;
        pthread_create(&tid, nullptr, Count, (void*)i);
        usleep(1000);
    }

    sleep(3);
    
    cout << "main thread ctrl begin: " << endl;

    while(true) 
    {
        sleep(1);
        pthread_cond_signal(&cond);  // 唤醒在cond上等待的一个线程
        cout << "signal one thread....\n";
    }

    return 0;
}

// int tickets = 1000;

// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// class threadData
// {
// public:
//     threadData(int number)
//     {
//         threadname = "thread[" + to_string(number) + "]";
//     }
//     string threadname;
// };

// void* getTicket(void* args)
// {
//     threadData* td = static_cast<threadData*>(args);
//     const char* name = td->threadname.c_str();
//     while(true)
//     {
//        {   
//             LockGuard lockguard(&mutex);     // 临时的 LockGroud 对象， RAII风格
//             if(tickets > 0)
//             {
//                 usleep(1000);
//                 printf("who = %s, get a tickets = %d\n", name, tickets);
//                 tickets--;
                
//             }
//             else break;
//         }
//         usleep(13);	
//     }
//     cout << name << "quit.....\n";
//     return nullptr;
// }

// class threadData
// {
// public:
//     threadData(int number, pthread_mutex_t* mutex)
//     {
//         threadname = "thread[" + to_string(number) + "]";
//         mutex = mutex;
//     }
//     string threadname;
//     pthread_mutex_t* mutex;
// };

// void* getTicket(void* args)
// {
//     threadData* td = static_cast<threadData*>(args);
//     const char* name = td->threadname.c_str();
//     while(true)
//     {
//         pthread_mutex_lock(td->mutex);   // 申请锁成功，才能往后执行，不成功则一直阻塞。
//         if(tickets > 0)
//         {
//             usleep(1000);
//             printf("who = %s, get a tickets = %d\n", name, tickets);
//             tickets--;
//             pthread_mutex_unlock(td->mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->mutex);
//             break;
//         }
//         usleep(13);	
//     }
//     cout << name << "quit.....\n";
//     return nullptr;
// }


// int main()
// {
//     vector<pthread_t> tids;
//     vector<threadData*> thread_datas;
//     for(int i = 1; i <= 4; ++i)
//     {
//         pthread_t tid;
//         threadData* td = new threadData(i);
//         thread_datas.push_back(td);
//         pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
//         tids.push_back(tid);
//     }

//     for(auto &tid : tids) pthread_join(tid, nullptr);
//     for(auto &td : thread_datas) delete td;

//     return 0;
// }

//  // int g_val = 100;
//  __thread int g_val = 100;

// class threadData
// {
// public:
//     threadData(int number)
//     {
//         threadname = "thread[" + to_string(number) + "]";
//     }
//     string threadname;
// };

// string toHex(pthread_t tid)
// {
//     char hex[128] = {0};
//     sprintf(hex, "%p", tid);
//     return hex;
// }

// void *threadRoutine(void* args)
// {
//     threadData* td = static_cast<threadData*>(args);
//     const char* name = td->threadname.c_str();
//     int cnt = 0;
//     int i = 0;
//     while(i < 10)
//     {
//         cout << "pid: " << getpid() << ", tid: " << toHex(pthread_self()) << endl;
        
//         // cout << "pid: " << getpid() << ", tid: " << toHex(pthread_self()) 
//         //     << ", threadname: " << name << ", g_val: " << g_val << ", &g_val: " << &g_val << endl;
        
//         // cout << "pid: " << getpid() << ", tid: " << toHex(pthread_self()) 
//         //     << ", threadname: " << name << ", cnt: " << cnt << ", &cnt" << &cnt << endl;
//         ++i, ++g_val;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for(int i = 0; i < 3; i++)
//     {
//         pthread_t tid;
//         threadData* td = new threadData(i);
//         pthread_create(&tid, NULL, threadRoutine, (void*)td);
//         tids.push_back(tid);
//         usleep(100000);
//     }

//     for(auto &tid : tids) pthread_detach(tid);  // 分离线程

//     for(auto &tid : tids)
//     {
//         int n = pthread_join(tid, nullptr);
//         printf("n = %d, who = 0x%x, reason: %s\n", n, tid, strerror(n));
//     }
//     return 0;
// }


// string toHex(pthread_t tid)
// {
//     char hex[128] = {0};
//     sprintf(hex, "%p", tid);
//     return hex;
// }

// void *threadRun(void* args)
// {
//     while(true)
//     {
//         cout << (char*)args << " id: " << toHex(pthread_self()) << endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, NULL, threadRun, (void*)"thread[1]");
//     cout << "main thread create new thread, id: " << toHex(tid) << endl;
//     pthread_join(tid, nullptr);
//     return 0;
// }

// class Response
// {
// public:
//     Response(int result, int exitcode)
//         :_result(result), _exitcode(exitcode)
//     {}
// public:  
//     int _result;   // 计算结果
//     int _exitcode; // 计算结果是否可靠
// };

// class Request
// {
// public:
//     Request(int start, int end, const string &threadname)
//         :_start(start), _end(end), _threadname(threadname)
//     {}

//     long long CalSum(Response* resp)
//     {
//         for(int i = _start; i <= _end; i++)
//         {
//             // cout << rq->_threadname << " is runing, caling..., " << i << endl;
//             resp->_result += i;
//             usleep(100000);
//         }
//     }

// public:   
//     int _start;
//     int _end;
//     string _threadname;
// };


// void *sumCount(void *args) // 线程的参数和返回值，不仅仅可以用来进行传递一般参数，也可以传递对象！！
// {
//     Request *req = static_cast<Request*>(args);     
//     Response *resp = new Response(0,0);
//     req->CalSum(resp);
//     delete req;
//     return resp;
// }

// int main()
// {
//     pthread_t tid;
//     Request* req = new Request(1, 100, "thread 1");
//     pthread_create(&tid, nullptr, sumCount, req);

//     void* ret;
//     pthread_join(tid, &ret);
//     Response *resp = static_cast<Response*>(ret);
//     cout << "resp->result: " << resp->_result << ", exitcode: " << resp->_exitcode << endl;
//     delete resp;
//     return 0;
// }

// int g_val = 0;

// void *threadRun(void* args)
// {
//     const char* name = (const char*) args;
//     int cnt = 5;
//     while(cnt--)
//     {
//         printf("%s pid: %d, g_val: %d, &g_val: 0x%p\n", name, getpid(), g_val, &g_val);
//         // std::cout << "new thread: " << getpid() << std::endl;
//         sleep(1);
//         if(cnt == 0) break;
//     } 
//     pthread_exit((void*)100);
//     return (void*)100;    // 线程不会返回到 main 函数，执行完线程函数后 就退出了。
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRun, (void*)"Thread[1]");
//     sleep(1);   // 1s后取消线程
//     pthread_cancel(tid);

//     // while(1)
//     // {
//     //     printf("main thread pid: %d, g_val: %d, &g_val: 0x%p, create new thread tid: %p\n", getpid(), g_val, &g_val, tid);
//     //     // std::cout << "main thread: " << getpid() << std::endl;
        
//     //     // printf("main thread pid: %d, g_val: %d, &g_val: 0x%p\n", getpid(), g_val, &g_val);
//     //     ++g_val;
//     //     sleep(1);
        
//     // }
    
//     // sleep(7);

//     PTHREAD_CANCELED;
//     cout << PTHREAD_CANCELED << endl;
//     void* retval;
//     pthread_join(tid, &retval);
//     cout << "main thread quit! " << "retval: " << (long long)retval << endl;   // 64位平台下指针8字节，强转int会发生数据截断，gcc报错
//     return 0;
// }
